#include "restclient.h"

#include <QCoreApplication>
#include <QNetworkRequest>
#include <QTemporaryFile>
#include <QUrl>

#include <QDebug>

RESTClient::RESTClient(QObject *parent) :
    QObject(parent)
{
    qnam = new QNetworkAccessManager(this);
    connect(qnam, SIGNAL(finished(QNetworkReply*)), this, SLOT(finishedSlot(QNetworkReply*)));

    currentFile = NULL;
}

QString RESTClient::search(const QString &query, const QStringList &stoplist)
{
    mode = SEARCH;
    reply = qnam->get(QNetworkRequest(Query(query, stoplist).getQueryUrl()));
    while(!this->isReady())
        qApp->processEvents();
    return searchResult;
}


void RESTClient::clearIndex()
{
    oneShot = true;
    reply = qnam->deleteResource(QNetworkRequest(QUrl("http://localhost:9200/docs/wiki")));
    while(!this->isReady())
        qApp->processEvents();
}

void RESTClient::setSimilarity(const QString &similarity)
{
    oneShot = true;
    QTemporaryFile *json = new QTemporaryFile();
    json->open();
    QTextStream out(json);
    out << QString("{\"wiki\":{\"properties\":{\"content\":{\"type\":\"string\",\"similarity\":\"%1\"},\"title\":{\"type\":\"string\"}}}}").arg(similarity);
    json->close();
    json->open();
    reply = qnam->put(QNetworkRequest(QUrl("http://localhost:9200/docs/wiki/_mapping")), json);
    while(!this->isReady())
        qApp->processEvents();
    json->close();
    delete json;
}

void RESTClient::putDocument(QFile *doc, const QString &name, bool oneShot)
{
    this->oneShot = oneShot;

    QUrl url("http://localhost:9200/docs/wiki/" + name);
    doc->open(QIODevice::ReadOnly);

    reply = qnam->put(QNetworkRequest(url), doc);
}

void RESTClient::putAllDocuments(const QDir &directory)
{
    mode = PUT_DOCUMENT;
    currentFileIndex = -1;
    fileNum = directory.count();
    dirPath = directory.absolutePath();
    files = directory.entryList();

    putNextDocument();
}

void RESTClient::getSearchResult(const Query &query, bool oneShot)
{
    this->oneShot = oneShot;
    Query q = query;
    qnam->get(QNetworkRequest(q.getQueryUrl()));
}

void RESTClient::getAllSearchResults(const QList<Query> *queries)
{
    mode = GET_SEARCH_RESULT;
    currentFileIndex = -1;
    fileNum = queries->size();

    this->queries = queries;
    searchResults.clear();

    getNextSearchResult();
}

void RESTClient::finishedSlot(QNetworkReply *reply)
{
    if(mode == SEARCH){
        //searchResult = reply.readAll();
        QVariantMap result = parser.parse(reply).toMap();
        QVariantList docs = result.value("hits").toMap().value("hits").toList();
        searchResult.clear();
        foreach(const QVariant &item, docs)
            searchResult += item.toMap().value("_id").toString() + "\n";
        return;
    }

    if(mode == GET_SEARCH_RESULT){
        QVariantMap result = parser.parse(reply).toMap();
        QVariantList docs = result.value("hits").toMap().value("hits").toList();
        searchResults << SearchResult();
        searchResults.last().time = result.value("took").toLongLong();
        foreach(const QVariant &item, docs)
            searchResults.last().docs << item.toMap().value("_id").toString();
    }

    if(oneShot){
        qDebug() << reply->readAll();
        emit finished();
    }
    else{
        if(currentFileIndex < fileNum - 1)
            switch(mode){
            case PUT_DOCUMENT:
                qDebug() << reply->readAll();
                putNextDocument();
                break;
            case GET_SEARCH_RESULT:
                getNextSearchResult();
                break;
            }
        else
            emit finished();
    }
}

void RESTClient::putNextDocument()
{
    currentFileIndex++;
    const QString &file = files.at(currentFileIndex);
    delete currentFile;
    currentFile = new QFile(dirPath + "/" + file);
    putDocument(currentFile, file.mid(0, file.size() - 5), false);
    //qDebug() << file;
}

void RESTClient::getNextSearchResult()
{
    currentFileIndex++;
    getSearchResult(queries->at(currentFileIndex), false);
}
